<?php

namespace App\Services;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

abstract class BaseService
{
    /**
     * 获取模型实例
     *
     * @return Model
     */
    abstract protected function getModel(): Model;

    /**
     * 创建记录
     *
     * @param array $data
     * @return Model
     */
    protected function createModel(array $data): Model
    {
        return DB::transaction(function () use ($data) {
            return $this->getModel()::create($data);
        });
    }

    /**
     * 更新记录
     *
     * @param Model $model
     * @param array $data
     * @return Model
     */
    protected function updateModel(Model $model, array $data): Model
    {
        return DB::transaction(function () use ($model, $data) {
            $model->update($data);
            return $model->fresh();
        });
    }

    /**
     * 删除记录
     *
     * @param Model $model
     * @return bool
     */
    protected function deleteModel(Model $model): bool
    {
        return DB::transaction(function () use ($model) {
            return $model->delete();
        });
    }

    /**
     * 构建查询
     *
     * @param array $filters
     * @return Builder
     */
    protected function buildQuery(array $filters = []): Builder
    {
        $query = $this->getModel()::query();

        foreach ($filters as $key => $value) {
            if ($value !== null && $value !== '') {
                $this->applyFilter($query, $key, $value);
            }
        }

        return $query;
    }

    /**
     * 应用过滤器
     *
     * @param Builder $query
     * @param string $key
     * @param mixed $value
     * @return void
     */
    protected function applyFilter(Builder $query, string $key, $value): void
    {
        $model = $this->getModel();
        $fillable = $model->getFillable();

        if (!in_array($key, $fillable)) {
            return;
        }

        // 如果是like查询
        if (is_string($value) && str_contains($value, '%')) {
            $query->where($key, 'like', $value);
        } else {
            $query->where($key, $value);
        }
    }
}

